//+------------------------------------------------------------------+
//|                                                        Trade.mqh |
//|                             Copyright 2000-2025, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#include <Object.h>
#include "OrderInfo.h"
#include "HistoryOrderInfo.h"
#include "PositionInfo.h"
#include "DealInfo.h"

//+------------------------------------------------------------------+
//| 日志级别枚举                                                     |
//+------------------------------------------------------------------+
enum ENUM_LOG_LEVELS
{
   LOG_LEVEL_NO    = 0,  // 无日志
   LOG_LEVEL_ERRORS = 1, // 仅错误日志
   LOG_LEVEL_ALL   = 2   // 所有日志
};

//+------------------------------------------------------------------+
//| 交易操作类                                                       |
//| 用途：执行交易操作的类                                           |
//|         继承自 CObject 类                                        |
//+------------------------------------------------------------------+
class CTrade : public CObject
{
protected:
   MqlTradeRequest   m_request;              // 交易请求数据结构
   MqlTradeResult    m_result;               // 交易结果数据结构
   MqlTradeCheckResult m_check_result;       // 交易检查结果数据结构
   bool              m_async_mode;           // 异步交易模式标志
   ulong             m_magic;                // 专家顾问魔术码
   ulong             m_deviation;            // 最大允许滑点
   ENUM_ORDER_TYPE_FILLING m_type_filling;  // 订单填充类型
   ENUM_ACCOUNT_MARGIN_MODE m_margin_mode;   // 保证金计算模式
   ENUM_LOG_LEVELS   m_log_level;            // 日志级别

public:
   /** 构造函数 */
   CTrade(void);
   
   /** 析构函数 */
   ~CTrade(void);
   
   /**
    * 设置日志级别
    * @param log_level 日志级别
    */
   void              LogLevel(const ENUM_LOG_LEVELS log_level);
   
   /**
    * 获取交易请求结构
    * @param request 输出请求结构
    */
   void              Request(MqlTradeRequest &request) const;
   
   /**
    * 获取请求动作类型
    * @return 请求动作枚举值
    */
   ENUM_TRADE_REQUEST_ACTIONS RequestAction(void) const;
   
   /**
    * 获取请求动作描述
    * @return 请求动作描述字符串
    */
   string            RequestActionDescription(void) const;
   
   /**
    * 获取请求魔术码
    * @return 魔术码
    */
   ulong             RequestMagic(void) const;
   
   /**
    * 获取请求订单号
    * @return 订单号
    */
   ulong             RequestOrder(void) const;
   
   /**
    * 获取请求持仓号
    * @return 持仓号
    */
   ulong             RequestPosition(void) const;
   
   /**
    * 获取请求关联持仓号
    * @return 关联持仓号
    */
   ulong             RequestPositionBy(void) const;
   
   /**
    * 获取请求交易品种
    * @return 交易品种
    */
   string            RequestSymbol(void) const;
   
   /**
    * 获取请求交易量
    * @return 交易量
    */
   double            RequestVolume(void) const;
   
   /**
    * 获取请求价格
    * @return 价格
    */
   double            RequestPrice(void) const;
   
   /**
    * 获取请求限价价格
    * @return 限价价格
    */
   double            RequestStopLimit(void) const;
   
   /**
    * 获取请求止损价格
    * @return 止损价格
    */
   double            RequestSL(void) const;
   
   /**
    * 获取请求止盈价格
    * @return 止盈价格
    */
   double            RequestTP(void) const;
   
   /**
    * 获取请求滑点
    * @return 滑点
    */
   ulong             RequestDeviation(void) const;
   
   /**
    * 获取请求订单类型
    * @return 订单类型枚举值
    */
   ENUM_ORDER_TYPE   RequestType(void) const;
   
   /**
    * 获取请求订单类型描述
    * @return 订单类型描述字符串
    */
   string            RequestTypeDescription(void) const;
   
   /**
    * 获取请求订单填充类型
    * @return 订单填充类型枚举值
    */
   ENUM_ORDER_TYPE_FILLING RequestTypeFilling(void) const;
   
   /**
    * 获取请求订单填充类型描述
    * @return 订单填充类型描述字符串
    */
   string            RequestTypeFillingDescription(void) const;
   
   /**
    * 获取请求订单时间类型
    * @return 订单时间类型枚举值
    */
   ENUM_ORDER_TYPE_TIME RequestTypeTime(void) const;
   
   /**
    * 获取请求订单时间类型描述
    * @return 订单时间类型描述字符串
    */
   string            RequestTypeTimeDescription(void) const;
   
   /**
    * 获取请求订单过期时间
    * @return 过期时间
    */
   datetime          RequestExpiration(void) const;
   
   /**
    * 获取请求订单注释
    * @return 订单注释
    */
   string            RequestComment(void) const;
   
   /**
    * 获取交易结果结构
    * @param result 输出结果结构
    */
   void              Result(MqlTradeResult &result) const;
   
   /**
    * 获取交易返回码
    * @return 返回码
    */
   uint              ResultRetcode(void) const;
   
   /**
    * 获取交易返回码描述
    * @return 返回码描述字符串
    */
   string            ResultRetcodeDescription(void) const;
   
   /**
    * 获取外部返回码
    * @return 外部返回码
    */
   int               ResultRetcodeExternal(void) const;
   
   /**
    * 获取成交单号
    * @return 成交单号
    */
   ulong             ResultDeal(void) const;
   
   /**
    * 获取订单号
    * @return 订单号
    */
   ulong             ResultOrder(void) const;
   
   /**
    * 获取成交交易量
    * @return 交易量
    */
   double            ResultVolume(void) const;
   
   /**
    * 获取成交价格
    * @return 价格
    */
   double            ResultPrice(void) const;
   
   /**
    * 获取当前买价
    * @return 买价
    */
   double            ResultBid(void) const;
   
   /**
    * 获取当前卖价
    * @return 卖价
    */
   double            ResultAsk(void) const;
   
   /**
    * 获取结果注释
    * @return 注释
    */
   string            ResultComment(void) const;
   
   /**
    * 获取交易检查结果结构
    * @param check_result 输出检查结果结构
    */
   void              CheckResult(MqlTradeCheckResult &check_result) const;
   
   /**
    * 获取检查返回码
    * @return 返回码
    */
   uint              CheckResultRetcode(void) const;
   
   /**
    * 获取检查返回码描述
    * @return 返回码描述字符串
    */
   string            CheckResultRetcodeDescription(void) const;
   
   /**
    * 获取检查余额
    * @return 余额
    */
   double            CheckResultBalance(void) const;
   
   /**
    * 获取检查净值
    * @return 净值
    */
   double            CheckResultEquity(void) const;
   
   /**
    * 获取检查利润
    * @return 利润
    */
   double            CheckResultProfit(void) const;
   
   /**
    * 获取检查保证金
    * @return 保证金
    */
   double            CheckResultMargin(void) const;
   
   /**
    * 获取检查可用保证金
    * @return 可用保证金
    */
   double            CheckResultMarginFree(void) const;
   
   /**
    * 获取检查保证金水平
    * @return 保证金水平
    */
   double            CheckResultMarginLevel(void) const;
   
   /**
    * 获取检查注释
    * @return 注释
    */
   string            CheckResultComment(void) const;
   
   /**
    * 设置异步模式
    * @param mode 异步模式标志
    */
   void              SetAsyncMode(const bool mode);
   
   /**
    * 设置专家魔术码
    * @param magic 魔术码
    */
   void              SetExpertMagicNumber(const ulong magic);
   
   /**
    * 设置滑点（点数）
    * @param deviation 滑点点数
    */
   void              SetDeviationInPoints(const ulong deviation);
   
   /**
    * 设置订单填充类型
    * @param filling 填充类型枚举值
    */
   void              SetTypeFilling(const ENUM_ORDER_TYPE_FILLING filling);
   
   /**
    * 根据交易品种设置填充类型
    * @param symbol 交易品种
    * @return 成功返回 true，失败返回 false
    */
   bool              SetTypeFillingBySymbol(const string symbol);
   
   /**
    * 设置保证金模式
    */
   void              SetMarginMode(void);
   
   /**
    * 开仓
    * @param symbol 交易品种
    * @param order_type 订单类型
    * @param volume 交易量
    * @param price 价格
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionOpen(const string symbol, const ENUM_ORDER_TYPE order_type, const double volume,
                                  const double price, const double sl, const double tp, const string comment = "");
   
   /**
    * 修改持仓
    * @param symbol 交易品种
    * @param sl 止损价格
    * @param tp 止盈价格
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionModify(const string symbol, const double sl, const double tp);
   
   /**
    * 修改持仓（通过持仓号）
    * @param ticket 持仓号
    * @param sl 止损价格
    * @param tp 止盈价格
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionModify(const ulong ticket, const double sl, const double tp);
   
   /**
    * 平仓
    * @param symbol 交易品种
    * @param deviation 滑点
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionClose(const string symbol, const ulong deviation = ULONG_MAX);
   
   /**
    * 平仓（通过持仓号）
    * @param ticket 持仓号
    * @param deviation 滑点
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionClose(const ulong ticket, const ulong deviation = ULONG_MAX);
   
   /**
    * 对冲平仓
    * @param ticket 持仓号
    * @param ticket_by 对冲持仓号
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionCloseBy(const ulong ticket, const ulong ticket_by);
   
   /**
    * 部分平仓
    * @param symbol 交易品种
    * @param volume 平仓量
    * @param deviation 滑点
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionClosePartial(const string symbol, const double volume, const ulong deviation = ULONG_MAX);
   
   /**
    * 部分平仓（通过持仓号）
    * @param ticket 持仓号
    * @param volume 平仓量
    * @param deviation 滑点
    * @return 成功返回 true，失败返回 false
    */
   bool              PositionClosePartial(const ulong ticket, const double volume, const ulong deviation = ULONG_MAX);
   
   /**
    * 挂单
    * @param symbol 交易品种
    * @param order_type 订单类型
    * @param volume 交易量
    * @param limit_price 限价价格
    * @param price 价格
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param type_time 时间类型
    * @param expiration 过期时间
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              OrderOpen(const string symbol, const ENUM_ORDER_TYPE order_type, const double volume,
                               const double limit_price, const double price, const double sl, const double tp,
                               ENUM_ORDER_TYPE_TIME type_time = ORDER_TIME_GTC, const datetime expiration = 0,
                               const string comment = "");
   
   /**
    * 修改挂单
    * @param ticket 订单号
    * @param price 价格
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param type_time 时间类型
    * @param expiration 过期时间
    * @param stoplimit 限价价格
    * @return 成功返回 true，失败返回 false
    */
   bool              OrderModify(const ulong ticket, const double price, const double sl, const double tp,
                                 const ENUM_ORDER_TYPE_TIME type_time, const datetime expiration, const double stoplimit = 0.0);
   
   /**
    * 删除挂单
    * @param ticket 订单号
    * @return 成功返回 true，失败返回 false
    */
   bool              OrderDelete(const ulong ticket);
   
   /**
    * 买入
    * @param volume 交易量
    * @param symbol 交易品种
    * @param price 价格
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              Buy(const double volume, const string symbol = NULL, double price = 0.0, const double sl = 0.0, const double tp = 0.0, const string comment = "");
   
   /**
    * 卖出
    * @param volume 交易量
    * @param symbol 交易品种
    * @param price 价格
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              Sell(const double volume, const string symbol = NULL, double price = 0.0, const double sl = 0.0, const double tp = 0.0, const string comment = "");
   
   /**
    * 买入限价单
    * @param volume 交易量
    * @param price 价格
    * @param symbol 交易品种
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param type_time 时间类型
    * @param expiration 过期时间
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              BuyLimit(const double volume, const double price, const string symbol = NULL, const double sl = 0.0, const double tp = 0.0,
                              const ENUM_ORDER_TYPE_TIME type_time = ORDER_TIME_GTC, const datetime expiration = 0, const string comment = "");
   
   /**
    * 买入止损单
    * @param volume 交易量
    * @param price 价格
    * @param symbol 交易品种
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param type_time 时间类型
    * @param expiration 过期时间
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              BuyStop(const double volume, const double price, const string symbol = NULL, const double sl = 0.0, const double tp = 0.0,
                             const ENUM_ORDER_TYPE_TIME type_time = ORDER_TIME_GTC, const datetime expiration = 0, const string comment = "");
   
   /**
    * 卖出限价单
    * @param volume 交易量
    * @param price 价格
    * @param symbol 交易品种
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param type_time 时间类型
    * @param expiration 过期时间
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              SellLimit(const double volume, const double price, const string symbol = NULL, const double sl = 0.0, const double tp = 0.0,
                               const ENUM_ORDER_TYPE_TIME type_time = ORDER_TIME_GTC, const datetime expiration = 0, const string comment = "");
   
   /**
    * 卖出止损单
    * @param volume 交易量
    * @param price 价格
    * @param symbol 交易品种
    * @param sl 止损价格
    * @param tp 止盈价格
    * @param type_time 时间类型
    * @param expiration 过期时间
    * @param comment 注释
    * @return 成功返回 true，失败返回 false
    */
   bool              SellStop(const double volume, const double price, const string symbol = NULL, const double sl = 0.0, const double tp = 0.0,
                              const ENUM_ORDER_TYPE_TIME type_time = ORDER_TIME_GTC, const datetime expiration = 0, const string comment = "");
   
   /**
    * 检查交易量
    * @param symbol 交易品种
    * @param volume 交易量
    * @param price 价格
    * @param order_type 订单类型
    * @return 可交易量
    */
   virtual double    CheckVolume(const string symbol, double volume, double price, ENUM_ORDER_TYPE order_type);
   
   /**
    * 检查订单
    * @param request 交易请求
    * @param check_result 检查结果
    * @return 成功返回 true，失败返回 false
    */
   virtual bool      OrderCheck(const MqlTradeRequest &request, MqlTradeCheckResult &check_result);
   
   /**
    * 发送订单
    * @param request 交易请求
    * @param result 交易结果
    * @return 成功返回 true，失败返回 false
    */
   virtual bool      OrderSend(const MqlTradeRequest &request, MqlTradeResult &result);
   
   /**
    * 打印请求信息
    */
   void              PrintRequest(void) const;
   
   /**
    * 打印结果信息
    */
   void              PrintResult(void) const;
   
   /**
    * 格式化持仓类型
    * @param str 输出字符串
    * @param type 持仓类型
    * @return 格式化后的字符串
    */
   string            FormatPositionType(string &str, const uint type) const;
   
   /**
    * 格式化订单类型
    * @param str 输出字符串
    * @param type 订单类型
    * @return 格式化后的字符串
    */
   string            FormatOrderType(string &str, const uint type) const;
   
   /**
    * 格式化订单状态
    * @param str 输出字符串
    * @param status 订单状态
    * @return 格式化后的字符串
    */
   string            FormatOrderStatus(string &str, const uint status) const;
   
   /**
    * 格式化订单填充类型
    * @param str 输出字符串
    * @param type 填充类型
    * @return 格式化后的字符串
    */
   string            FormatOrderTypeFilling(string &str, const uint type) const;
   
   /**
    * 格式化订单时间类型
    * @param str 输出字符串
    * @param type 时间类型
    * @return 格式化后的字符串
    */
   string            FormatOrderTypeTime(string &str, const uint type) const;
   
   /**
    * 格式化订单信息
    * @param str 输出字符串
    * @return 格式化后的订单信息
    */
   string            FormatOrder(string &str) const;
   
   /**
    * 格式化订单价格
    * @param str 输出字符串
    * @param price_order 订单价格
    * @param price_trigger 触发价格
    * @param digits 小数点位数
    * @return 格式化后的价格字符串
    */
   string            FormatPrice(string &str, const double price_order, const double price_trigger, const uint digits) const;
   
   /**
    * 格式化交易请求
    * @param str 输出字符串
    * @param request 交易请求
    * @return 格式化后的请求字符串
    */
   string            FormatRequest(string &str, const MqlTradeRequest &request) const;
   
   /**
    * 格式化交易结果
    * @param str 输出字符串
    * @param request 交易请求
    * @param result 交易结果
    * @return 格式化后的结果字符串
    */
   string            FormatRequestResult(string &str, const MqlTradeRequest &request, const MqlTradeResult &result) const;

protected:
   /**
    * 检查填充类型
    * @param symbol 交易品种
    * @return 成功返回 true，失败返回 false
    */
   bool              FillingCheck(const string symbol);
   
   /**
    * 检查过期时间
    * @param symbol 交易品种
    * @return 成功返回 true，失败返回 false
    */
   bool              ExpirationCheck(const string symbol);
   
   /**
    * 检查订单类型
    * @param symbol 交易品种
    * @return 成功返回 true，失败返回 false
    */
   bool              OrderTypeCheck(const string symbol);
   
   /**
    * 清除结构体数据
    */
   void              ClearStructures(void);
   
   /**
    * 检查是否停止
    * @param function 函数名
    * @return 已停止返回 true，否则返回 false
    */
   bool              IsStopped(const string function);
   
   /**
    * 检查是否为对冲模式
    * @return 对冲模式返回 true，否则返回 false
    */
   bool              IsHedging(void) const;
   
   /**
    * 选择持仓
    * @param symbol 交易品种
    * @return 成功返回 true，失败返回 false
    */
   bool              SelectPosition(const string symbol);
};
//+------------------------------------------------------------------+